using System.IO;
using System.Linq;
using UnityEditorInternal;
using UnityEngine;

namespace LS.UnityExtensions.Editor
{
    public abstract class ProjectSettingScriptableObject<T> : EditorScriptableObject where T : ProjectSettingScriptableObject<T>
    {
        private static ProjectSettingScriptableObject<T> s_Instance = null;

        public static T Instance
        {
            get
            {
                if (s_Instance != null) return (T)s_Instance;
                s_Instance = LoadOrCreate();
                return (T)s_Instance;
            }

            set
            {
                s_Instance = value;
                Save(value);
            }
        }
        
        private static T LoadOrCreate()
        {
            var type = typeof(T);
            string path = $"ProjectSettings/{type.Name}.asset";
            T setting = null;
            if (File.Exists(path))
            {
                setting = (T)(InternalEditorUtility.LoadSerializedFileAndForget(path).Single());
            }
            else
            {
                setting = ScriptableObject.CreateInstance<T>();
                Save(setting);
            }

            return setting;
        }

        private static void Save(T setting)
        {
            var type = typeof(T);
            string path = $"ProjectSettings/{type.Name}.asset";
            InternalEditorUtility.SaveToSerializedFileAndForget(new[] { setting }, path, true);
        }

        public void Save()
        {
            Save((T)this);
        }
    }
}